package com.googlecode.gendevcode.service.basic;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.googlecode.gendevcode.common.Cache;
import com.googlecode.gendevcode.common.Util;
import com.googlecode.gendevcode.common.VelocityFactory;
import com.googlecode.gendevcode.model.ProjectXml;
import com.googlecode.gendevcode.model.ServiceConfigXml;
import com.googlecode.gendevcode.model.pdm.ColumnPdmXml;
import com.googlecode.gendevcode.model.pdm.TablePdmXml;
import com.googlecode.gendevcode.model.pdm.ViewPdmXml;
import com.googlecode.gendevcode.service.GenCodeFilesService;
import com.googlecode.gendevcode.service.ProjectConfigService;

/**
 * 生成代码文件基础类
 * @author devilishking
 *
 */
public abstract class GenCodeFilesServiceSupport extends ServiceSupport<GenCodeFilesServiceSupport> 
												 implements GenCodeFilesService {
	/**
	 * 创建Spring的hibernate配置文件信息
	 * @param tablePdmXmlList 待生成的表信息列表
	 * @param viewMap	                视图集合<视图编号, 视图信息>
	 * @param projectXml  	     项目信息
	 * @throws Exception
	 */
	public void genHibernateXml(List<TablePdmXml> tablePdmXmlList, Map<String, ViewPdmXml> viewMap, ProjectXml projectXml) throws Exception{
		Map<String, List<TablePdmXml>> tablePdmXmlListMap = getTablePdmXmlListMap(tablePdmXmlList);
		StringBuffer xmlText = new StringBuffer();
		Iterator<Entry<String, ViewPdmXml>> it = viewMap.entrySet().iterator();
		while(it.hasNext()){
			Entry<String, ViewPdmXml> entry = it.next();
			ViewPdmXml viewPdmXml = entry.getValue();
			List<TablePdmXml> dataList = tablePdmXmlListMap.get(viewPdmXml.getId());
			if (dataList != null){
				xmlText.append("<!-- ").append(viewPdmXml.getPackageCode()).append("[start] -->\r\n");
				for(TablePdmXml tablePdmXml : dataList){
					StringBuffer beanId = (new StringBuffer()).append(tablePdmXml.getClassName().substring(0, 1).toLowerCase())
															  .append(tablePdmXml.getClassName().substring(1));
					StringBuffer classPath = (new StringBuffer()).append(viewPdmXml.getPackageCode())
															     .append(".dao.impl.")
															     .append(tablePdmXml.getClassName())
															     .append("DaoImpl");
					xmlText.append("	<!--").append(beanId).append("-START-->\r\n")
						   .append("	<bean id=\"")
						   .append(beanId).append("Dao\" class=\"")
						   .append(classPath)
						   .append("\" autowire=\"byName\"/>\r\n")
						   .append("	<!--").append(beanId).append("-END-->\r\n");					
				}
				xmlText.append("<!-- ").append(viewPdmXml.getPackageCode()).append("[end] -->\r\n");
			}
		}
		if (xmlText.length() > 0){
			Util.writeFile(xmlText.toString(), 
						   (new StringBuffer()).append(projectXml.getResourcesPath())
						   					   .append("/insertHibernate_")
						   					   .append(String.valueOf(System.currentTimeMillis()))
						   					   .append(".xml")
						   					   .toString());
		}
	}

	/**
	 * 创建Spring的service配置文件信息
	 * @param tablePdmXmlList 待生成的表信息列表
	 * @param viewMap	                视图集合<视图编号, 视图信息>
	 * @param projectXml  	     项目信息
	 * @throws Exception
	 */
	public void genServiceXml(List<TablePdmXml> tablePdmXmlList, Map<String, ViewPdmXml> viewMap, ProjectXml projectXml) throws Exception{
		Map<String, List<TablePdmXml>> tablePdmXmlListMap = getTablePdmXmlListMap(tablePdmXmlList);
		StringBuffer xmlText = new StringBuffer();
		Iterator<Entry<String, ViewPdmXml>> it = viewMap.entrySet().iterator();
		while(it.hasNext()){
			Entry<String, ViewPdmXml> entry = it.next();
			ViewPdmXml viewPdmXml = entry.getValue();
			List<TablePdmXml> dataList = tablePdmXmlListMap.get(viewPdmXml.getId());
			if (dataList != null){
				xmlText.append("<!-- ").append(viewPdmXml.getPackageCode()).append("[start] -->\r\n");
				for(TablePdmXml tablePdmXml : dataList){
					StringBuffer beanId = (new StringBuffer()).append(tablePdmXml.getClassName().substring(0, 1).toLowerCase())
															  .append(tablePdmXml.getClassName().substring(1));
					StringBuffer classPath = (new StringBuffer()).append(viewPdmXml.getPackageCode())
															     .append(".service.impl.")
															     .append(tablePdmXml.getClassName())
															     .append("ServiceImpl");
					xmlText.append("	<!--").append(beanId).append("-START-->\r\n")	
						   .append("	<bean id=\"").append(beanId).append("Service\" class=\"").append(classPath).append("\" autowire=\"byName\"/>\r\n")
						   .append("	<!--").append(beanId).append("-END-->\r\n");
				}
				xmlText.append("<!-- ").append(viewPdmXml.getPackageCode()).append("[end] -->\r\n");
			}
		}
		if (xmlText.length() > 0){
			Util.writeFile(xmlText.toString(), 
						   (new StringBuffer()).append(projectXml.getResourcesPath())
						   					   .append("/insertService_")
						   					   .append(String.valueOf(System.currentTimeMillis()))
						   					   .append(".xml")
						   					   .toString());
		}
	}

	/**
	 * 创建字典文件
	 * @param tablePdmXmlList 待生成的表信息列表
	 * @param viewMap	                视图集合<视图编号, 视图信息>
	 * @param projectXml  	     项目信息
	 * @throws Exception
	 */
	public void genDictionaryXml(List<TablePdmXml> tablePdmXmlList, Map<String, ViewPdmXml> viewMap, ProjectXml projectXml) throws Exception{
		StringBuffer xmlText = new StringBuffer();

		
		xmlText.append("<codes>\r\n");
		for(TablePdmXml tablePdmXml : tablePdmXmlList){
			ViewPdmXml viewPdmXml = viewMap.get(tablePdmXml.getViewId());
			String[] packageCodeArr = viewPdmXml.getPackageCode().split("\\.");
			String module = packageCodeArr[packageCodeArr.length-1].toUpperCase();
			List<ColumnPdmXml> columnPdmXmlList = tablePdmXml.getColumnPdmXmlList();
			for(ColumnPdmXml columnPdmXml : columnPdmXmlList){
				if (columnPdmXml.getDictionary() != null && columnPdmXml.getDictionary().trim().length() > 0){
					xmlText.append("	<code>\r\n")
						   .append("		<name>").append(tablePdmXml.getName()).append("_").append(columnPdmXml.getName()).append("</name>\r\n")
						   .append("		<value>").append(module).append("_").append(tablePdmXml.getClassName().toUpperCase()).append("_").append(columnPdmXml.getCode().toUpperCase()).append("</value>\r\n")
						   .append("		<codeValues>\r\n");					
					String[] dictionarys = columnPdmXml.getDictionary().replace("[", "").replace("]", "").split(";");
					for(String dictionary : dictionarys){
						if (dictionary.trim().length() > 0){
							String[] codeValue = dictionary.split("：");
							xmlText.append("			<codeValue>\r\n")
								   .append("				<name>").append(codeValue[1].trim()).append("</name>\r\n")
								   .append("				<value>").append(codeValue[0].trim()).append("</value>\r\n")
								   .append("			</codeValue>\r\n");
						}
					}					
					xmlText.append("		</codeValues>\r\n")
						   .append("	</code>\r\n");
				}
			}
		}
		xmlText.append("</codes>");
		
		if (xmlText.length() > 0){
			Util.writeFile(xmlText.toString(), 
						   (new StringBuffer()).append(projectXml.getResourcesPath())
						   					   .append("/createDictionary_")
						   					   .append(String.valueOf(System.currentTimeMillis()))
						   					   .append(".xml")
						   					   .toString());
		}
	}	

	/**
	 * 创建代码文件  
	 * @param tablePdmXmlList 待生成的表信息列表
	 * @param viewMap	                视图集合<视图编号, 视图信息>
	 * @param genLevel 	                项目生成级别
	 * @param projectXml      项目信息
	 * @throws Exception
	 */
	public void genCodeFilesXml(List<TablePdmXml> tablePdmXmlList, Map<String, ViewPdmXml> viewMap, String genLevel, ProjectXml projectXml) throws Exception{
		for(TablePdmXml tablePdmXml : tablePdmXmlList){
			ViewPdmXml viewPdmXml = viewMap.get(tablePdmXml.getViewId());
			String packageName = (new StringBuffer()).append(viewPdmXml.getPackageCode())
												  	 .append(".")
												  	 .append(genLevel)
												  	 .toString();
			String[] packageCode = viewPdmXml.getPackageCode().split("\\.");
			String packageFolder = packageCode[packageCode.length-1];
	
			StringBuffer suffix = new StringBuffer();
			if (!"model".equals(genLevel) && !"pages".equals(genLevel)){
				String level = genLevel.indexOf("web.") == 0 ? genLevel.substring(4) : genLevel;
				String[] strs = level.replace(".", ",").split(",");
				for(String str : strs){
					suffix.append(str.substring(0,1).toUpperCase())
						  .append(str.substring(1));
				}
			}
			
			String className = (new StringBuffer()).append(tablePdmXml.getClassName())
												   .append(suffix)
												   .toString();
			
			Map<String, Object> dataMap = new HashMap<String, Object>();
			dataMap.put("tablePdmXml", tablePdmXml);
			dataMap.put("viewPdmXml", viewPdmXml);
			dataMap.put("userName", projectXml.getUserName());
			dataMap.put("nowYear", (new SimpleDateFormat("yyyy")).format(new Date()));
			dataMap.put("projectXml", projectXml);
			dataMap.put("className", className);
			dataMap.put("packageName", packageName);
			dataMap.put("packageFolder", packageFolder);
			
			String projectType = Cache.getInstance().getProjectTypeList().get(projectXml.getType());
			
			if ("pages".equals(genLevel)){
				genPagesFile(dataMap, tablePdmXml, viewPdmXml, projectXml);
			}
			else{
				ProjectConfigService projectConfigService = Cache.getInstance().getBean(ServiceConfigXml.ID_PROJECTCONFIG,
																						projectXml.getType(),
																					    ProjectConfigService.class);
				String genFilePath = projectConfigService.getGenFilePath(viewPdmXml.getPackageCode(), 
																		 genLevel, 
																		 projectXml);
				File file = new File((new StringBuffer()).append(genFilePath)
														 .append("/")
														 .toString());
				if (!file.exists()) file.mkdirs();

				if ("model".equals(genLevel)){
					file = new File((new StringBuffer()).append(genFilePath)
					  		  					        .append("/").append(className)
									  				    .append(".java").toString());
					if (file.exists()){
						FileInputStream fileInputStream  = null;
						InputStreamReader inputStreamReader = null;
						BufferedReader bufferedReader = null;
						try{
							fileInputStream = new FileInputStream(file.getAbsolutePath());
							inputStreamReader = new InputStreamReader(fileInputStream, "UTF-8");
							bufferedReader = new BufferedReader(inputStreamReader);
							boolean dictionaryStart = false;
							boolean customMethodStart = false;
							StringBuilder dictionary = new StringBuilder();
							StringBuilder customMethod = new StringBuilder();
							String str = "";
							while ((str = bufferedReader.readLine()) != null){
								if (dictionaryStart && !str.contains("//endregion 字典")) dictionary.append(str).append("\r\n");
								if (str.contains("//region 字典")) dictionaryStart = true;								
								if (str.contains("//endregion 字典")) dictionaryStart = false;

								if (customMethodStart && !str.contains("//endregion 自定义方法")) customMethod.append(str).append("\r\n");
								if (str.contains("//region 自定义方法")) customMethodStart = true;
								if (str.contains("//endregion 自定义方法")) customMethodStart = false;
							}
							if (dictionary.length() > 0){
								dictionary.deleteCharAt(dictionary.length()-1);
								dictionary.deleteCharAt(dictionary.length()-1);
							}
							if (customMethod.length() > 0){
								customMethod.deleteCharAt(customMethod.length()-1);
								customMethod.deleteCharAt(customMethod.length()-1);
							}
							if (dictionary.toString().trim().length() > 0){
								boolean isRead = inputBoolean((new StringBuilder())
															  .append(tablePdmXml.getName())
															  .append("[")
															  .append(tablePdmXml.getCode())
															  .append("]")
															  .append("对应的model是否保留字典区的内容: true: ")
															  .toString(), true);
								if (isRead) dataMap.put("dictionary", dictionary);
							}
							if (customMethod.toString().trim().length() > 0){
								boolean isRead = inputBoolean((new StringBuilder())
															  .append(tablePdmXml.getName())
															  .append("[")
															  .append(tablePdmXml.getCode())
															  .append("]")
															  .append("对应的model是否保留自定义方法区的内容: true: ")
															  .toString(), true);
								if (isRead) dataMap.put("customMethod", customMethod);
							}
						}
						catch(Exception e){
							e.printStackTrace();
						}
						finally{
							if (bufferedReader != null) bufferedReader.close();
							if (inputStreamReader != null) inputStreamReader.close();
							if (fileInputStream != null) fileInputStream.close();
						}
					}
				}
				VelocityFactory.writeFile(dataMap, 
										  (new StringBuffer()).append(projectType)
										  					  .append("/").append(genLevel)
										  					  .append(".vm").toString(), 
										  (new StringBuffer()).append(genFilePath)
										  					  .append("/").append(className)
										  					  .append(".java").toString(), 
										  Cache.getInstance().getRootPath());
			}
		}
	}
	
	/**
	 * 创建页面文件
	 * @param dataMap     页面所属数据
	 * @param tablePdmXml 表信息
	 * @param viewPdmXml  视图信息
	 * @param projectXml  项目信息
	 * @param 
	 * @throws Exception
	 */
	public abstract void genPagesFile(Map<String, Object> dataMap, TablePdmXml tablePdmXml, ViewPdmXml viewPdmXml, ProjectXml projectXml) throws Exception;

	/**
	 * 重组待生成的表信息列表
	 * @param tablePdmXmlList 待生成的表信息列表
	 * @return
	 * @throws Exception
	 */
	private Map<String, List<TablePdmXml>> getTablePdmXmlListMap(List<TablePdmXml> tablePdmXmlList) throws Exception{
		Map<String, List<TablePdmXml>> tablePdmXmlListMap = new HashMap<String, List<TablePdmXml>>();
		for(TablePdmXml tablePdmXml : tablePdmXmlList){
			List<TablePdmXml> dataList = tablePdmXmlListMap.get(tablePdmXml.getViewId());
			if (dataList == null){
				dataList = new ArrayList<TablePdmXml>();
			}
			dataList.add(tablePdmXml);
			tablePdmXmlListMap.put(tablePdmXml.getViewId(), dataList);
		}
		return tablePdmXmlListMap;
	}
}